#include "ota_version.h"
#include "ota_http_curl.h"
#include "cJSON.h"


#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <openssl/sha.h>
#include <sys/reboot.h>
#include <unistd.h>
#include "log.h"

#define SHA1_DIGEST_LENGTH 20

char *file_to_sha1(const char *filename) {
    FILE *file = fopen(filename, "rb");
    if (!file) {
        perror("无法打开文件");
        return NULL;
    }

    unsigned char digest[SHA1_DIGEST_LENGTH];
    SHA_CTX sha_ctx;
    SHA1_Init(&sha_ctx);

    unsigned char buffer[1024];
    size_t bytes_read;

    while ((bytes_read = fread(buffer, 1, sizeof(buffer), file)) > 0) {
        SHA1_Update(&sha_ctx, buffer, bytes_read);
    }

    SHA1_Final(digest, &sha_ctx);
    fclose(file);

    // 转换为十六进制字符串
    char *sha1_str = (char *)malloc(SHA1_DIGEST_LENGTH * 2 + 1);
    if (!sha1_str) {
        perror("内存分配失败");
        return NULL;
    }

    for (int i = 0; i < SHA1_DIGEST_LENGTH; ++i) {
        sprintf(sha1_str + i * 2, "%02x", digest[i]);
    }
    sha1_str[SHA1_DIGEST_LENGTH * 2] = '\0';

    return sha1_str;
}



/**
 * @brief 执行ota更新
 * 步骤：
 * 1 网关程序 通过http请求  获取ota服务器的版本信息
   2解析信息  
  3比较版本号 
4 如果本地版本号低  http 则下载最新程序
 5用本地的程序生成一个验证码 
 6验证码比较 
 7重启

 */
int ota_version_update()
{

//     * 1 网关程序 通过http请求  获取ota服务器的版本信息
    response_body_t *response_body= ota_http_curl_get(OTA_VERSION_URL);
//     2解析信息  
    if(response_body==NULL)
    {  
        perror("ota_http_curl_get error");
        return -1;
    }
    cJSON *root = cJSON_Parse(response_body->str);
    cJSON *major_cjson= cJSON_GetObjectItem(root, "major");
    cJSON *minor_cjson= cJSON_GetObjectItem(root, "minor");
    cJSON *patch_cjson= cJSON_GetObjectItem(root, "patch");

    int major_ota=major_cjson->valueint;
    int minor_ota=minor_cjson->valueint;
    int patch_ota=patch_cjson->valueint;

//    3比较版本号 
    if(major_ota>OTA_VERSION_MAJOR||
       (major_ota==OTA_VERSION_MAJOR&&minor_ota>OTA_VERSION_MINOR)||
       (major_ota==OTA_VERSION_MAJOR&&minor_ota==OTA_VERSION_MINOR&&patch_ota>OTA_VERSION_PATCH)
    )
    {
        //  4 如果本地版本号低  http 则下载最新程序
        log_info(" 需要更新ota版本:%d.%d.%d",major_ota,minor_ota,patch_ota);
        int ret= ota_http_curl_download(OTA_VERSION_URL_DOWNLOAD,OTA_VERSION_LOCAL_PATH);
        if(ret==-1)
        {   
            log_error("下载失败");
            return -1;
        }

        //   5用本地的程序生成一个验证码 
       char *sha1_local=  file_to_sha1(OTA_VERSION_LOCAL_PATH);
      //   6验证码比较 
      cJSON *sha_cjson= cJSON_GetObjectItem(root, "sha1");
      char *sha1_ota= sha_cjson->valuestring;


      if(strcmp(sha1_local,sha1_ota)==0)
      {
          log_info("sha1验证成功,重启更新");
          //   7重启
          reboot(RB_AUTOBOOT);
      }
      else
      {
          log_error("sha1验证失败");
          unlink(OTA_VERSION_LOCAL_PATH);
          cJSON_Delete(root);
          free(response_body);
          return -1;
      }

    }
    cJSON_Delete(root);
    free(response_body);
    return 0;

}


/**
 * @brief 周期性检查ota版本(每日)
 */
void ota_version_check_daily()
{
    while(1)
    {
        sleep(24*60*60);
        ota_version_update();
    }
}

/**
 * @brief 打印当前版本号
 */
void ota_version_print()
{
    printf("当前版本号:%d.%d.%d\n",OTA_VERSION_MAJOR,OTA_VERSION_MINOR,OTA_VERSION_PATCH);
}